package cn.codesugar.network

import android.annotation.SuppressLint
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import cn.codesugar.network.databinding.ActivityMainBinding
import cn.codesugar.network.retrofit.AppService
import cn.codesugar.network.retrofit.ServiceCreator
import com.google.gson.Gson
import okhttp3.*
import org.json.JSONArray
import org.xml.sax.Attributes
import org.xml.sax.InputSource
import org.xml.sax.helpers.DefaultHandler
import org.xmlpull.v1.XmlPullParser
import org.xmlpull.v1.XmlPullParserFactory
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import java.io.IOException
import java.io.StringReader
import java.lang.Exception
import java.lang.StringBuilder
import javax.xml.parsers.DocumentBuilder
import javax.xml.parsers.DocumentBuilderFactory
import javax.xml.parsers.SAXParserFactory

class MainActivity : AppCompatActivity() {

    @SuppressLint("SetJavaScriptEnabled")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        // 使用HttpUrlConnection发起网络请求
        binding.sendRequestWithHttpUrlConnectionBtn.setOnClickListener {
            val url = "http://10.89.20.119:8080/download?type=json"
            HttpUtil.sendRequestWithHttpUrlConnection(url, object: HttpCallbackListener {
                override fun onFinish(response: String) {
//                    parseXMLWithPull(response)
//                    parseJsonWithJSONObject(response)
                    parseJsonWithGson(response)
                    runOnUiThread {
                        binding.responseText.text = response
                    }
                }

                override fun onError(e: Exception) {
                    e.printStackTrace()
                }

            })
        }

        // 使用OkHttp发起请求
        binding.sendRequestWithOkHttpBtn.setOnClickListener {
            val url = "http://10.89.20.119:8080/download?type=json"
            HttpUtil.sendRequestWithOkHttp(url, object: Callback {
                override fun onFailure(call: Call, e: IOException) {
                    e.printStackTrace()
                }

                override fun onResponse(call: Call, response: Response) {
                    response.body?.string()?.let {
                        parseJsonWithGson(it)
                        runOnUiThread {
                            binding.responseText.text = it
                        }
                    }
                }

            })
        }

        // 使用retrofit发起请求
        binding.sendRequestWithRetrofitBtn.setOnClickListener {
//            val appService = ServiceCreator.create(AppService::class.java)
            val appService = ServiceCreator.create<AppService>()
            appService.getAppData("json").enqueue(object : retrofit2.Callback<Apps> {

                override fun onResponse(
                    call: retrofit2.Call<Apps>,
                    response: retrofit2.Response<Apps>
                ) {
                    val apps = response.body()
                    apps?.let {
                        binding.responseText.text = it.toString()
                        for (app in it) {
                            Log.e("Retrofit_GSON", "id:${app.id}")
                            Log.e("Retrofit_GSON", "name:${app.name}")
                            Log.e("Retrofit_GSON", "version:${app.version}")
                        }
                    }
                }

                override fun onFailure(call: retrofit2.Call<Apps>, t: Throwable) {
                    t.printStackTrace()
                }

            })
        }
    }

    /**
     * ==================================== 解析XML =================================================
     */

    /**
     * 使用pull方式解析xml
     */

    private fun parseXMLWithPull(xmlData: String) {
        try {
            val factory = XmlPullParserFactory.newInstance()
            val xmlPullParser = factory.newPullParser()
            xmlPullParser.setInput(StringReader(xmlData))
            var eventType = xmlPullParser.eventType
            var id = ""
            var name = ""
            var version = ""
            while (eventType != XmlPullParser.END_DOCUMENT) {
                val nodeName = xmlPullParser.name
                when (eventType) {
                    // 开始解析某个节点
                    XmlPullParser.START_TAG -> {
                        when (nodeName) {
                            "id" -> id = xmlPullParser.nextText()
                            "name" -> name = xmlPullParser.nextText()
                            "version" -> version = xmlPullParser.nextText()
                        }
                    }
                    // 完成解析某个节点
                    XmlPullParser.END_TAG -> {
                        if ("app" == nodeName) {
                            Log.d("MainActivity", "id is $id")
                            Log.d("MainActivity", "name is $name")
                            Log.d("MainActivity", "version is $version")
                        }
                    }
                }
                eventType = xmlPullParser.next()
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    /**
     * SAX解析方式
     */

    private fun parseXMLWithSAX(xmlData: String) {
        try {
            val factory = SAXParserFactory.newInstance()
            val xmlReader = factory.newSAXParser().xmlReader
            val handler = ContentHandler()
            // 将ContentHandler的实例设置到XMLReader中
            xmlReader.contentHandler = handler
            // 开始解析
            xmlReader.parse(InputSource(StringReader(xmlData)))
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    class ContentHandler : DefaultHandler() {

        private var nodeName = ""

        private lateinit var id: StringBuilder

        private lateinit var name: StringBuilder

        private lateinit var version: StringBuilder

        override fun startDocument() {
            // 开始解析XML
            id = StringBuilder()
            name = StringBuilder()
            version = StringBuilder()
        }

        override fun startElement(
            uri: String?,
            localName: String?,
            qName: String?,
            attributes: Attributes?
        ) {
            // 开始解析某个节点
            // 记录当前节点名
            localName?.let { nodeName = localName }
            Log.d("ContentHandler", "uri:$uri")
            Log.d("ContentHandler", "localName:$localName")
            Log.d("ContentHandler", "qName:$qName")
            Log.d("ContentHandler", "attributes:$attributes")
        }

        override fun characters(ch: CharArray?, start: Int, length: Int) {
            // 获取节点中内容
            // 根据当前节点名判断内容加入到哪一个StringBuilder对象中
            when (nodeName) {
                "id" -> id.append(ch, start, length)
                "name" -> name.append(ch, start, length)
                "version" -> version.append(ch, start, length)
            }
        }

        override fun endElement(uri: String?, localName: String?, qName: String?) {
            // 完成解析某个节点
            if ("app" == localName) {
                Log.d("ContentHandler", "id:${id.toString().trim()}")
                Log.d("ContentHandler", "name:${name.toString().trim()}")
                Log.d("ContentHandler", "version:${version.toString().trim()}")
                // 最后要将StringBuilder清空
                id.setLength(0)
                name.setLength(0)
                version.setLength(0)
            }
        }

        override fun endDocument() {
            // 完成整个XML解析
        }
    }

    /**
     * DOM解析
     */

    private fun parseXMLWithDOM(xmlData: String) {
        try {
            val factory = DocumentBuilderFactory.newInstance()
            val documentBuilder: DocumentBuilder = factory.newDocumentBuilder()
            val document = documentBuilder.parse(InputSource(StringReader(xmlData)))
            // 获取xml文档的中的元素根元素
            val root = document.documentElement
            // 获取根元素下的子节点
            val appsChildNodes = root.childNodes
            for (i in 0 until appsChildNodes.length) {
                // 获得根元素下的子节点
                val appNode = appsChildNodes.item(i)
                val appChildNodes = appNode.childNodes
                for (j in 0 until appChildNodes.length) {
                    val contentNode = appChildNodes.item(j)
                    when (contentNode.nodeName) {
                        "id" -> Log.e("DOM", "id:${contentNode.textContent}")
                        "name" -> Log.e("DOM", "name:${contentNode.textContent}")
                        "version" -> Log.e("DOM", "version:${contentNode.textContent}")
                    }
                }
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    /**
     * ==================================== 解析JSON =================================================
     */

    private fun parseJsonWithJSONObject(jsonData: String) {
        try {
            val jsonArray = JSONArray(jsonData)
            for (i in 0 until jsonArray.length()) {
                val jsonObject = jsonArray.getJSONObject(i)
                val id = jsonObject.getString("id")
                val name = jsonObject.getString("name")
                val version = jsonObject.getString("version")
                Log.e("JSONObject", "id:$id")
                Log.e("JSONObject", "name:$name")
                Log.e("JSONObject", "version:$version")
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    private fun parseJsonWithGson(jsonData: String) {
        val gson = Gson()
        val apps = gson.fromJson(jsonData, Apps::class.java)
        for (app in apps) {
            Log.e("GSON", "id:${app.id}")
            Log.e("GSON", "name:${app.name}")
            Log.e("GSON", "version:${app.version}")
        }
    }
}